use craftdig_datamodel::block::{
    msgs::*,
    ty::{BlockData, BlockReg},
    BlkId,
};
use craftdig_datamodel::message::*;
use craftdig_math::*;

use crate::registry::{GenericRegistry, RegistryKind};

/// Contains registries for all game logic information and behavior references.
/// Each client instance has a game registrar.  Constructed before client start.
pub struct GameRegistrar {
    block_ty_reg: BlockRegistry,
    block_msg_reg: MsgTyRegistry,
}

impl GameRegistrar {
    pub fn new(block_ty_reg: BlockRegistry, block_msg_reg: MsgTyRegistry) -> Self {
        Self {
            block_ty_reg,
            block_msg_reg,
        }
    }

    pub fn block_ty_reg(&self) -> &BlockRegistry {
        &self.block_ty_reg
    }

    pub fn block_msg_reg(&self) -> &MsgTyRegistry {
        &self.block_msg_reg
    }

    /// Looks up block type data by its block ID.
    pub fn get_block_tydata_by_id(&self, id: BlkId) -> Option<&BlockData> {
        self.block_ty_reg().get_by_id(id).map(|reg| reg.tydata())
    }
}

pub struct BlockRegKind;

impl RegistryKind for BlockRegKind {
    type RawIdent = u16;
    type Ident = BlkId;
    type Reg = BlockReg;

    fn next_ident(a: Self::RawIdent) -> Self::RawIdent {
        a + 1
    }
}

pub type BlockRegistry = GenericRegistry<BlockRegKind>;

pub struct MsgTyRegKind;

impl RegistryKind for MsgTyRegKind {
    type RawIdent = u16;
    type Ident = MsgTyId;
    type Reg = MsgTyReg;

    fn next_ident(a: Self::RawIdent) -> Self::RawIdent {
        a + 1
    }
}

pub type MsgTyRegistry = GenericRegistry<MsgTyRegKind>;
